package FilterDesigners.Butterworth;

import java.lang.Math;
import java.util.ArrayList;

public abstract class ButterworthFilter {

	public final double W1, W2, K1, K2, Wc;
	public final int ORDER;
	private ArrayList<Double> poleAngles = new ArrayList<Double>();
	protected ArrayList<Double> qValues = new ArrayList<Double>();
	protected ArrayList<Double> normalizedComponents = new ArrayList<Double>();
	private ArrayList<Double> scaledComponents = new ArrayList<Double>();
	
	
	public ButterworthFilter(double w1, double w2, double k1, double k2) {
		K1 = k1;
		K2 = k2;
		W1 = w1;
		W2 = w2;
		ORDER = calculateOrder();
		Wc= calculate3dBFreq();
		calculatePoleAngles();
		calculateQValues();
		calculateNormalizedComponents();
		
		
	}
	
	private int calculateOrder() {
		double dOrderNumerator = Math.log10( ( Math.pow(10.0,(K1/10.0)) - 1)/( Math.pow(10.0, (K2/10.0)) -1) );
		double dOrderDenominator = 2.0*Math.log10(W1/W2);
		return (int) Math.ceil(dOrderNumerator/dOrderDenominator);
	}
	
	protected abstract double calculate3dBFreq();
	
	public double get3dBFreq(){
		return Wc;
	}
	
	private void calculatePoleAngles(){
		double angleSeparation = 180.0/ORDER;
		if(ORDER % 2 == 1) {	// If the order is odd
			for(int i = 0; i <= ORDER/2; i++) {
				poleAngles.add(angleSeparation*i);
			}
		}
		
		if(ORDER % 2 == 0) { // If the order is even
			for(int i = 0; i < ORDER/2; i++) {
				
				poleAngles.add(angleSeparation/2.0 +angleSeparation*i);
			}
		}
	}
	
	public ArrayList<Double> getPoleAngles(){
		return poleAngles;
	}
	
	private void calculateQValues(){
		for(int i = 0; i < ORDER/2; i ++){
			if(poleAngles.get(0) == 0.0)
				i = 1;
			qValues.add(1/(2.0*Math.cos(poleAngles.get(i)*Math.PI/180.0)));
		}
	}
	
	public ArrayList<Double> getQValues(){
		return qValues;
	}
	
	protected abstract void calculateNormalizedComponents();
	
	public ArrayList<Double> getNormalizedComponents(){
		return normalizedComponents;
	}
	
	
	
}
